#include "ex06aa.cpp"
#include "pwext.hpp"
#include <stdio.h>

class malloc_arena
{
public:
	malloc_arena() :
		total_(0)
	{ 
		fprintf(stderr, "creating malloc_arena %p\n", this);
	}

	~malloc_arena()
	{
		fprintf(stderr, "destroying malloc_arena %p\n", this);
	}

	// just for show, count the bytes and return the pointer to itself
	void *get_block(size_t bytes)
	{
		total_ += bytes;
		fprintf(stderr, "malloc_arena %p: total %d\n", this, (int)total_);
		return this;
	}

	size_t total_;
};

// [[ex06ab]]
// DEBUG descr Usage of the thread-specific data key.
// its implementation is not important here
class malloc_arena; 

class malloc_tskey : public tskey
{
public:
	static void destroy_value(void *val)
	{
		delete (malloc_arena *)val;
	}

	malloc_tskey() :
		tskey(destroy_value)
	{ }

	malloc_arena *get()
	{
		malloc_arena *ma = (malloc_arena *)tskey::get();
		if (ma == 0) {
			ma = new malloc_arena;
			set(ma);
		}
		return ma;
	}
};

class our_malloc
{
public:
	static void *malloc(size_t bytes)
	{
		malloc_arena *ar = arenas_.get();
		return ar->get_block(bytes);
	}

protected:
	static malloc_tskey arenas_;
};
// END

// DEBUG from
malloc_tskey our_malloc::arenas_;

pw::event startev;

class worker : public pw::pwthread
{
public:
	void *execute()
	{
		startev.wait();
		for (int i = 0; i < 3; i++) {
			fprintf(stderr, "worker %p malloc_arena %p\n", this, our_malloc::malloc(10));
		}
		return 0;
	}
};

int main()
{
	worker w1, w2;

	w1.start();
	w2.start();

	startev.signal();

	w1.join();
	w2.join();

	return 0;
}

/* Sample output:
creating malloc_arena 0x7f937c0008c0
malloc_arena 0x7f937c0008c0: total 10
worker 0x7fff8cff3b60 malloc_arena 0x7f937c0008c0
creating malloc_arena 0x7f93840008c0
malloc_arena 0x7f93840008c0: total 10
worker 0x7fff8cff3bb0 malloc_arena 0x7f93840008c0
malloc_arena 0x7f93840008c0: total 20
worker 0x7fff8cff3bb0 malloc_arena 0x7f93840008c0
malloc_arena 0x7f93840008c0: total 30
worker 0x7fff8cff3bb0 malloc_arena 0x7f93840008c0
destroying malloc_arena 0x7f93840008c0
malloc_arena 0x7f937c0008c0: total 20
worker 0x7fff8cff3b60 malloc_arena 0x7f937c0008c0
malloc_arena 0x7f937c0008c0: total 30
worker 0x7fff8cff3b60 malloc_arena 0x7f937c0008c0
destroying malloc_arena 0x7f937c0008c0
*/
